package com.server.common.exception;

import com.server.common.api.ApiResult;
import com.server.common.enums.ResultCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.List;
import java.util.Set;


/**
 * @Author zgr
 * @create 2023/7/9 16:49
 */
@Slf4j
@RestControllerAdvice
@Component
public class GolbalExceptionHandler {

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }

    @ExceptionHandler
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiResult handle(ValidationException e) {
        log.error("请求异常：{}", e.getMessage());
        if (e instanceof ConstraintViolationException) {
            ConstraintViolationException exs = (ConstraintViolationException) e;

            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
                //打印验证不通过的信息
                log.error("请求异常：{}",item.getMessage());
            }
        }
        return ApiResult.fail(ResultCodeEnum.Fail.getCode(), "请求异常： " + e.getMessage());
    }

    @ExceptionHandler(value = BindException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult bindException(Exception e) {
        if (e instanceof BindException) {
            BindException exs = (BindException) e;
            List<FieldError> fieldErrors = exs.getFieldErrors();
            for (FieldError item : fieldErrors) {
                log.error("请求异常：{}", item.getDefaultMessage());
            }
        }
        log.error("数据绑定异常：{}", e.getMessage());
        return ApiResult.fail(ResultCodeEnum.Fail.getCode(), "数据绑定异常：" + e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        // 注意哦，这里返回类型是自定义响应体
        return ApiResult.fail(ResultCodeEnum.Fail.getCode(), objectError.getDefaultMessage());
    }

    /**
     * 处理空指针的异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = NullPointerException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiResult nullPointerException(NullPointerException e){
        log.error("发生空指针异常！请求异常:{}",e.getMessage());
        return ApiResult.fail(ResultCodeEnum.Fail.getCode(), e.getMessage());
    }


    @ExceptionHandler(value = BusinessException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult businessException(BusinessException e) {
        log.error("发生业务异常！请求异常：{}", e.getMessage());
        return ApiResult.fail(ResultCodeEnum.Fail.getCode(), e.getMessage());
    }



    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult defaultException(Exception e) {
        log.error("请求异常：{}", e.getMessage());
        return ApiResult.fail(ResultCodeEnum.Fail.getCode(), e.getMessage());
    }
}
